package cn.learn.jdk8new.stream;

import cn.learn.jdk8new.Employee;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 2、中间操作
 *
 * @author huangyezhan
 * @version 1.0
 * @date 2020年03月24日15:03
 */
public class StreamDemo2 {

    private List<Employee> employees = Arrays.asList(
            new Employee("张三", 28, "天河", 5555.8),
            new Employee("李四", 28, "荔湾", 15886.5),
            new Employee("王五", 30, "白云", 8886.4),
            new Employee("赵六", 41, "花都", 6786.1),
            new Employee("田七", 36, "从化", 13886.7),
            new Employee("八妹", 22, "越秀", 4668.5)
    );

    /*
     * 多个中间操作可以连接起来形成一个流水线，除非流水线上触发终止操作，否则中间操作不会执行任何的处理！
     * 而在终止操作时一次性全部处理，称为“惰性求值”。
     */

    /**
     * 一、筛选与切片
     * filter   接受Lambda，从流中排除某些元素。
     * limit    截断流，使其元素不超过给定数量。
     * skip(n)  跳过元素，返回一个扔掉了前n个元素的流。若流中元数不足n个，则返回一个空流。与limit（n）互补
     * distinct 筛选，通过流所生成元素的hashCode（）和equals（）去除重复元素
     */
    //内部迭代：迭代操作由Stream API完成
    @Test
    public void test1() {
        //中间操作不会执行任何操作
        Stream<Employee> stream1 = employees.stream()
                .skip(3)
                /*.filter((e) -> {
                    System.out.println("==============");//验证中间是否会操作
                    return e.getAge() > 35;
                })*/;

        //执行了终止操作后，才会一次性执行所有的操作，“惰性求值”
        stream1.forEach(System.out::println);

        System.out.println("======================");

        List<Employee> collect = employees.stream()
                .skip(1)
                .limit(2)
                .collect(Collectors.toList())
                ;

        System.out.println(collect.size());
        for (Employee employee : collect) {
            System.out.println(employee);
        }
    }

    //外部迭代
    public void test2() {
        Iterator<Employee> it = employees.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }

    /**
     * 二、映射
     * map      接受Lambda，将元素转换成其他形式或提取信息。接受一个函数作为参数，该函数回会被应用到每个元素上，并将其映射成一个新的元素。
     * flatMap  接受一个函数作为参数，将流中的每个值都换成另一个流，然后把所有流连成一个流
     */
    @Test
    public void test3() {
        List<String> list = Arrays.asList("aa", "bb", "cc", "dd", "ee");
        list.stream()
                .map((s) -> s.toUpperCase())
                .forEach(System.out::println);

        employees.stream()
                .map(Employee::getName)
                .forEach(System.out::println);

        //===================================================================

        System.out.println("============================================");
        Stream<Stream<Character>> stream = list.stream()
                .map(StreamDemo2::filterCharacter);//{{a,a},{b,b}} 相当于分成了一个个流；类似于 list的 add  addAll

        stream.forEach((e) -> {
            e.forEach(System.out::println);
        });

        System.out.println("--------------------------------------------");
        Stream<Character> stream2 = list.stream()
                .flatMap(StreamDemo2::filterCharacter);//{a,a,b,b} 多个流合并成一个；类似于 list的 add  addAll

        stream2.forEach(System.out::println);

    }

    public static Stream<Character> filterCharacter(String str) {
        List<Character> list = new ArrayList<>();
        for (Character ch : str.toCharArray()) {
            list.add(ch);
        }
        return list.stream();
    }

    /**
     * 三、排序
     *  sorted()    自然排序（Comparable）
     *  sorted(Comparable com)  定制排序（Comparable）
     */
    @Test
    public void test4(){
        List<String> list = Arrays.asList("ccc", "ddd", "aaa", "e", "ff");
        list.stream().sorted().forEach(System.out::println);

        System.out.println("--------------------------------------------");

        employees.stream()
                .sorted((e1,e2)->{
                    if(e1.getAge().equals(e2.getAge())){
                        return -e1.getName().compareTo(e2.getName());
                    }else {
                        return e1.getAge().compareTo(e2.getAge());
                    }
                }).forEach(System.out::println);
    }

    @Test
    public void test5(){
        Integer a = 4;
        Integer b = 5;
        Integer c = 5;
        Integer d = 3;
        List<Integer> list = new ArrayList<>();
        list.add(a);
        list.add(b);
        list.add(c);
        list.add(d);

        List<Integer> collect = list.stream()
                .sorted((e1, e2) -> {
                    return -e1.compareTo(e2);
                })
                .collect(Collectors.toList());
        System.out.println(collect);
    }


}
